/*****************************************************************
 MYD Engine v0.1

 File: myd_directInput.cpp
 Created: 09/07/09
*****************************************************************/

#include "myd_directInput.h"
//------------------------------------------------------------------------------
using namespace myd;
//------------------------------------------------------------------------------
DirectInput::DirectInput(HINSTANCE hInstance, HWND hWnd):
KeyboardObj(NULL),
MouseObj(NULL),
KeyboardDev(NULL),
MouseDev(NULL),
AppInstance(hInstance),
WindowHandler(hWnd)
{

}
//------------------------------------------------------------------------------
DirectInput::~DirectInput()
{
	Unacquire();
	Deinit();
}
//------------------------------------------------------------------------------
bool DirectInput::Init()
{
	static HRESULT hr;

/*Inicializamos el Teclado*/
	//Cargamos el objeto de teclado
	hr = DirectInput8Create(AppInstance, 
							DIRECTINPUT_VERSION, 
							IID_IDirectInput8,
							(void**)&KeyboardObj, 
							NULL );

	if(FAILED(hr))
		return false;

	//Creamos el device
	hr = KeyboardObj->CreateDevice(GUID_SysKeyboard, &KeyboardDev, NULL);
	if(FAILED(hr))
		return false;

	//set the keyboard data format (no queres saberlo)
	hr = KeyboardDev->SetDataFormat(&c_dfDIKeyboard);
	if(FAILED(hr))
		return false;

	//Asigna exclusividad en caso de estar en full screen (Falta implementar)
	hr = KeyboardDev->SetCooperativeLevel(WindowHandler, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
	if(FAILED(hr))
		return false;

	//Adquirimos el keyboard
	hr = KeyboardDev->Acquire();
	if(FAILED(hr))
		return false;

/*Inicializamos el Mouse*/
	//Cargamos el objeto de mouse
	hr = DirectInput8Create(AppInstance, 
						DIRECTINPUT_VERSION, 
						IID_IDirectInput8,
						(void**)&MouseObj,	
						NULL );
    
	if(FAILED(hr))
		return false;

	//Creamos el device
	hr = MouseObj->CreateDevice(GUID_SysMouse, &MouseDev, NULL);
	if(FAILED(hr))
		return false;

	//set the mouse data format (no queres saberlo)
	hr = MouseDev->SetDataFormat(&c_dfDIMouse);
	if(FAILED(hr))
		return false;

	//Asigna exclusividad en caso de estar en full screen (Falta implementar)
	hr = MouseDev->SetCooperativeLevel(WindowHandler, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
	if(FAILED(hr))
		return false;

	//acquire the mouse
	hr = MouseDev->Acquire();
	if(FAILED(hr))
		return false;

	return true;
}
//------------------------------------------------------------------------------
void DirectInput::Update()
{
	Reacquire();
	UpdateMouse();
	UpdateKeyboard();
}
//------------------------------------------------------------------------------
void DirectInput::Deinit()
{
    if (KeyboardObj)					// if DirectInput Object One exists
    {
        if (KeyboardDev)				// if KeyboardDevice Object exists
        {
            KeyboardDev->Unacquire();	// then unacquire it
            KeyboardDev->Release();		// and release it
            KeyboardDev = NULL;			// and NULL the pointer
        }
        KeyboardObj->Release();			// release the DirectInput Object One
        KeyboardObj = NULL;				// and NULL the pointer
    }

    if (MouseObj)						// if DirectInput Object Two exists
    {
        if (MouseDev)					// if MouseDevice Object exists
        {
            MouseDev->Unacquire();		// then unacquire it
            MouseDev->Release();		// and release it
            MouseDev = NULL;			// and NULL the pointer
        }
        MouseObj->Release();			// release de DirectInput Object Two
        MouseObj = NULL;				// and NULL the pointer
    }
}
//------------------------------------------------------------------------------
void DirectInput::Reset()
{
	// resets all the devices status buffers
	Input::Reset();
	ZeroMemory(&MouseState, sizeof(MouseState));
}
//------------------------------------------------------------------------------
void DirectInput::Acquire()
{
	// get the keyboard device state
	memcpy(KeyPrevBuffer, KeyBuffer, 256);
	ZeroMemory(&KeyBuffer, sizeof(KeyBuffer));
	KeyboardDev->GetDeviceState(sizeof(KeyBuffer), &KeyBuffer);

	// get the mouse device state
	ZeroMemory(&MouseState, sizeof(MouseState));
	MouseDev->GetDeviceState( sizeof(MouseState), &MouseState );

	// update the mouse absolute position
	m_alMouseScreenAbsPos[POS_X] += MouseState.lX;
	m_alMouseScreenAbsPos[POS_Y] -= MouseState.lY;
	m_alMouseScreenAbsPos[POS_Z] += MouseState.lZ;

	// set the mouse relative position
	m_alMouseRelPos[POS_X] = MouseState.lX;
	m_alMouseRelPos[POS_Y] = MouseState.lY;
	m_alMouseRelPos[POS_Z] = MouseState.lZ;

	// updates the mouse button states
	m_aucMouseBut[MB_1] = MouseState.rgbButtons[MB_1] & 0x80;
	m_aucMouseBut[MB_2] = MouseState.rgbButtons[MB_2] & 0x80;
	m_aucMouseBut[MB_3] = MouseState.rgbButtons[MB_3] & 0x80;
}
//------------------------------------------------------------------------------
void DirectInput::Reacquire()
{
	// reacquire all the input devices
	if(MouseDev) MouseDev->Acquire();
	if(KeyboardDev) KeyboardDev->Acquire();
	Acquire();
}
//------------------------------------------------------------------------------
void DirectInput::Unacquire()
{
	// unacquire all the input devices
	ZeroMemory(&KeyBuffer, sizeof(KeyBuffer));
	ZeroMemory(&MouseState, sizeof(MouseState));

	if(MouseDev) MouseDev->Unacquire();
	if(KeyboardDev) KeyboardDev->Unacquire();
}
//------------------------------------------------------------------------------